package org.com.yz.dubbo.web.ctrl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import org.com.yz.common.constant.PayConstant;
import org.com.yz.common.util.FtpUtil;
import org.com.yz.common.util.RandomNum;
import org.com.yz.common.util.ToolUtil;
import org.com.yz.dal.dao.mapper.*;
import org.com.yz.dal.dao.model.*;
import org.com.yz.dubbo.api.service.*;
import org.com.yz.dubbo.web.core.ChineseCalendar;
import org.com.yz.dubbo.web.service.ScheuldBankCardService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 定时任务控制类
 *
 * @ClassName TimingReconciliationCtr
 * @Author wzc
 * @Date 2018/7/31 16:49
 **/
@RestController
public class TimingReconciliationCtr {


    private static Logger log = LoggerFactory.getLogger(TimingReconciliationCtr.class);

    @Reference(version = "1.0.0", timeout = 80000, retries = 0)
    private ITransactionDetailsService transactionDetailsService;
    @Reference(version = "1.0.0", timeout = 80000, retries = 0)
    private IHisAccntOnwayService iHisAccntOnwayService;
    @Reference(version = "1.0.0", timeout = 80000, retries = 0)
    private IMchConfigService iMchConfigService;
    @Reference(version = "1.0.0", timeout = 80000, retries = 0)
    private IWithDrawMchAccntService iWithDrawMchAccntService;
    @Reference(version = "1.0.0", timeout = 80000, retries = 0)
    private IProblemRecordService iProblemRecordService;

    @Autowired
    private ScheuldBankCardService scheuldBankCardService;
    @Autowired
    private BankCardMapper bankCardMapper;
    @Autowired
    private ChineseCalendar cc;
    @Autowired
    private MchAccntMapper mchAccntMapper;
    @Autowired
    private HisAccntSupplierAssMapper hisAccntSupplierAssMapper;
    @Autowired
    private DownloadInfoMapper downloadInfoMapper;

    @Autowired
    private PassportXyReportDetailMapper passportXyReportDetailMapper;

    /**
     * 在途1 定时平账
     * *每个工作日的凌晨到中午12点，每58分钟执行定时平账逻辑
     * **1.查询所有配置商户信息
     * **2.遍历商户，查询商户上一个工作日到昨天的在途总额+今日已平过的在途总额（平在途后会记录在途平账明细，type为reconciliation）
     * **3.如果有在途金额，并且有到账金额，则执行平账--更新存管、在途、记录相关明细、更改子商户可用余额
     */
           @Scheduled(cron = "0 0/58 0-12 * * ?")//0到12点，每50分钟执行一次
    @RequestMapping(value = "/api/reconOnway")
    public void timingReconciliation() throws Exception {
        MchConfig mchConfig = new MchConfig();
        mchConfig.setAccntType("0");
        List<MchConfig> mchConfigList = iMchConfigService.listCongi(mchConfig);    //1.查询所有配置商户
        //String lastWordDay = findLastWorkDay();//上一个工作日
        String today = DateUtil.format(new Date(), "yyyy-MM-dd");
        Date date = DateUtil.parseDate(today);
        String   lastWordDay = DateUtil.offsetDay(date, -1).toDateStr();
        /*if (!cc.isWorkday(today)) {
            log.info(today + "今天是非工作日，无支付结算通道进账金额");
            return;
        }*/
        if (1 == org.com.yz.common.util.DateUtil.compareDate(org.com.yz.common.util.DateUtil.formatDate(new Date(), "HH:mm:ss"), "13:00:00", "HH:mm:ss")) {
            log.info(today + "支付通道结算时间已过");
//            return;
        }
        try {
            for (MchConfig mchConfig1 : mchConfigList) {
                transactionDetailsService.reconciliationOnway(lastWordDay, today, mchConfig1);
            }
        } catch (Exception e) {
            log.info(ToolUtil.getExceptionMsg(e));
            log.info("【定时平账】在途1定时平账失败，错误信息：" + e.getMessage());
        }

    }

    @RequestMapping(value = "/api/reconOnways")
    public void timingReconciliations(String today,String lastWordDay) throws Exception {
        MchConfig mchConfig = new MchConfig();
        mchConfig.setAccntType("0");
        List<MchConfig> mchConfigList = iMchConfigService.listCongi(mchConfig);    //1.查询所有配置商户
        //String lastWordDay = findLastWorkDay();//上一个工作日
        /*String today = DateUtil.format(new Date(), "yyyy-MM-dd");
        Date date = DateUtil.parseDate(today);
        String   lastWordDay = DateUtil.offsetDay(date, -1).toDateStr();*/
        /*if (!cc.isWorkday(today)) {
            log.info(today + "今天是非工作日，无支付结算通道进账金额");
            return;
        }*/
        if (1 == org.com.yz.common.util.DateUtil.compareDate(org.com.yz.common.util.DateUtil.formatDate(new Date(), "HH:mm:ss"), "13:00:00", "HH:mm:ss")) {
            log.info(today + "支付通道结算时间已过");
//            return;
        }
        try {
            for (MchConfig mchConfig1 : mchConfigList) {
                transactionDetailsService.reconciliationOnway(lastWordDay, today, mchConfig1);
            }
        } catch (Exception e) {
            log.info(ToolUtil.getExceptionMsg(e));
            log.info("【定时平账】在途1定时平账失败，错误信息：" + e.getMessage());
        }

    }


    /**
     * 在途2 定时平账
     */
            @Scheduled(cron = "0 */61 * * * ?")
    @RequestMapping(value = "/api/reconTwo")
    public void timingReconciliationTwo() throws Exception {
        String lastWordDay = findLastWorkDay();//上一个工作日
        String today = DateUtil.format(new Date(), "yyyy-MM-dd");
        MchConfig mchConfig = new MchConfig();
        mchConfig.setSpuerMoney("1"); //超额提现 1开启 0关闭
        List<MchConfig> mchConfigList = iMchConfigService.listCongi(mchConfig);    //查询超额提现的商户
        try {
            for (MchConfig mchConfig1 : mchConfigList) {
                transactionDetailsService.reconciliationOnway2(lastWordDay, today, mchConfig1);
            }
        } catch (Exception e) {
            log.info("【定时平账】在途2定时平账失败，错误信息：" + e.getMessage());
        }

    }

    /**
     * 定时记录问题键
     * *每个工作日12点执行定时记录问题键逻辑
     * **1.查询所有配置商户信息
     * **2.遍历商户，查询商户上一个工作日到昨天的在途总额+今日已平过的在途总额（平在途后会记录在途平账明细，type为reconciliation）
     * **3.如果此时还有未平完的账，则记录问题键，在后管系统-对账管理-问题键记录菜单中展示，每个商户一天一条记录（理论上）
     * **4.针对问题键记录，用户可以选择强制平账，或再次平账（1，已处理--触发平在途1逻辑；2.扣除手续费）
     */
           @Scheduled(cron = "0 0 12 * * ?")//每天中午12点
    @RequestMapping(value = "/api/recoProblem")
    public void timingOnwayProblem() throws Exception {
        String today = DateUtil.format(new Date(), "yyyy-MM-dd");
        /*if (!cc.isWorkday(today)) {
            log.info(today + "今天是非工作日，无支付结算通道进账金额");
            return;
        }*/
        try {
            MchConfig mchConfig = new MchConfig();
            mchConfig.setAccntType("0");
            List<MchConfig> mchConfigList = iMchConfigService.listCongi(mchConfig);    //1.查询所有配置商户
            for (MchConfig mchConfigSupser : mchConfigList) {
                String mchNo = mchConfigSupser.getMchNo();
                String versionNo = mchConfigSupser.getVersionNo();
                //查询上一个工作日的在途1总额
//                String lastWordDay = findLastWorkDay();//上一个工作日
                Date date = DateUtil.parseDate(today);
                String    lastWordDay = DateUtil.offsetDay(date, -1).toDateStr();
                Long balance = 0L;
                //查询上一个工作日到昨天的在途总额（例如：今天周一，上周五，周末的支付及在途，全部在今天结算到账；   今天10月8号，9.30-10.7日的支付，全部在10.8号结算到账）
                HisAccntOnway hisAccntOnway = iHisAccntOnwayService.selectCountOnwayByTime(mchNo, lastWordDay, today,versionNo);
                if (ToolUtil.isNotEmpty(hisAccntOnway) && ToolUtil.isNotEmpty(hisAccntOnway.getEventAmt())) {
                    balance = hisAccntOnway.getEventAmt();
                    log.info("\n 查询到【" + mchNo + "】：在途总额为" + balance);
                    if (balance != 0) {
                        //记录问题键
                        ProblemRecord problemRecord = new ProblemRecord();
                        problemRecord.setMchNo(mchNo);//商户号
                        problemRecord.setProblemType("unleveledAcc");//问题键类型 未平账
                        problemRecord.setProblemDetail(String.valueOf(balance));//问题明细
                        problemRecord.setProblemTime(new Date());//问题发生时间
                        problemRecord.setCreateTime(new Date());//创建时间
                        problemRecord.setStatus("0");//问题键状态 0：未解决 1：已解决
                        iProblemRecordService.insertProblemRecord(problemRecord);
                    }
                } else {
                    log.info("\n 查询到【" + mchNo + "】：在途总额为" + balance);
                }

            }
        } catch (Exception e) {
            log.info(ToolUtil.getExceptionMsg(e));
        }
    }


    /**
     * param
     * Description: 准备金定时平账
     * author wzc
     * date 2018/8/30 20:11
     */
           @Scheduled(cron = "0 */55 * * * ?")
    @RequestMapping(value = "/api/timingPrePay")
    public void timingPrePay() {
        try {

            MchAccnt mchAccnt = new MchAccnt();
            mchAccnt.setAccntType("depository");
            //查询所有的存管户
            List<MchAccnt> mchAccntList1 = mchAccntMapper.selectMchAccnt(mchAccnt);
            for (MchAccnt mchAccnt1:mchAccntList1) {
                transactionDetailsService.timingPrepay(mchAccnt1);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 定时查询提现处理中的记录
     */
            @Scheduled(cron = "0 */60 * * * ?")
    @RequestMapping(value = "/api/queryWithdraw")
    public void timingReconciliationWithdraw() throws InterruptedException {
        //查询提现记录表里--所有提现状态为未决的
        WithDrawInfo withDrawInfo = new WithDrawInfo();
        withDrawInfo.setStatus("3");
        List<WithDrawInfo> withDrawInfoList = iWithDrawMchAccntService.selectWithDrawInfo(withDrawInfo);
        //按商户分类，得出有几个商户
        Map<String, List<WithDrawInfo>> resultMap = new HashMap<>(); // 最终要的结果
        for (WithDrawInfo dataItem : withDrawInfoList) {
            if (resultMap.containsKey(dataItem.getMchNo())) {
                resultMap.get(dataItem.getMchNo()).add(dataItem);
            } else {
                List<WithDrawInfo> list = new ArrayList<>();
                list.add(dataItem);
                resultMap.put(dataItem.getMchNo(), list);
            }
        }
        iWithDrawMchAccntService.httpStatus(resultMap, 1);
    }


    /**
     * 定时更新 上一个工作日前的提现记录为成功
     *
     * return
     * Author WZC  每天凌晨1点执行一次
     * Description
     * Date 21:27 2018/10/9
     * Param
     */
           @Scheduled(cron = "0 0 1 * * ?")
    public void updateStatus() throws Exception {
        String lastWorkDay = findLastWorkDay();//查找上一个工作日
        //当前日期是工作日
        iWithDrawMchAccntService.updateWithDrawInfoByTime(lastWorkDay);


    }


    /**
     * 查找上一个工作日
     *
     * return
     * throws Exception
     */
//    @RequestMapping(value = "/api/test3.htm")
    private String findLastWorkDay() throws Exception {
        //当前日期是工作日
        String weekDay = "";
        String today = DateUtil.format(new Date(), "yyyy-MM-dd");
        String dateNew;
        if (cc.isWorkday(today)) {
            Date date = DateUtil.parseDate(today);
            //前一天
            for (int i = 1; i < 30; i++) {
                dateNew = DateUtil.offsetDay(date, -i).toDateStr();
                if (cc.isWorkday(dateNew)) {
                    weekDay = dateNew;
                    break;
                }
            }
        }
        System.out.println(weekDay);
        return weekDay;
    }


    /**
     * 定时查询更新未绑定成功的银行卡数据（对私）
     */
            @Scheduled(cron = "0 */30 * * * ?")
    public void updateBankCard() {
        try {
            List<BankCard> bankCardList = bankCardMapper.selectNoSuccess();//查询对私待认证及认证处理中
            log.info(cn.hutool.core.date.DateUtil.now() + "==定时任务查询到:" + bankCardList.size() + "条未认证成功的银行卡");
            for (BankCard bankCardfr : bankCardList) {
                scheuldBankCardService.updateBankCard(bankCardfr);
            }
        } catch (Exception e) {
            log.info(ToolUtil.getExceptionMsg(e));
        }
    }

    /**
     * 定时将待结算供应商账户的资金，转移到供应商子账户（等同于分账，只是不记在途账）
     */
    //TODO 待确定  每个供应商的账期相同与否
    public void transferSupplierAss(){
        //查询商户配置信息
        MchConfig mchConfig = new MchConfig();
        mchConfig.setUseAssurance("Y");
        mchConfig.setMchNo("0");
        //查询开启了担保供应商的商户配置信息（商户配置表可能要加账期字段，标识每个平台的供应商结算账期是多少，或者根据供应商来，在账户表加账期字段）
        List<MchConfig> mchConfigList = iMchConfigService.listCongi(mchConfig);
        if(ToolUtil.isNotEmpty(mchConfigList)){
            //遍历集合，对每个有供应商担保账户的商户，进行供应商资金账期结算操作
            //计算有多少待结算资金，按账期或者何种方式
            for (MchConfig config : mchConfigList){
                String mchNo = config.getMchNo();//商户号
                //String accountPeriod = config.getAccountPeriod();//账期
                //根据商户号查询有哪些待结算供应商子账户
                MchAccnt mchAccnt = new MchAccnt();
                mchAccnt.setMchNo(mchNo);//商户号
                mchAccnt.setAccntType(PayConstant.DEPOSIT_SUPPLIER_ASSURANCE);//账户类型
                List<MchAccnt> mchAccntList = mchAccntMapper.selectMchAccnt(mchAccnt);
                if(ToolUtil.isNotEmpty(mchAccntList)){
                    //遍历所有待结算供应商子账户，进行资金账期结算操作
                    for(MchAccnt accnt : mchAccntList){
                        String mchAccntNo = accnt.getMchAccntNo();//待结算供应商子账户号
                        //String accountPeriod = accnt.getAccountPeriod();//账期
                        //根据账户号查询有多少待结算资金
                        int amt = hisAccntSupplierAssMapper.selectHisAccntSupplierAssCount(mchNo,mchAccntNo);
                        //执行结算逻辑（1.待结算账户-  2.供应商账户+  3.待结算账户、供应商账户明细）


                    }
                }
            }
        }
    }


    /**
     * 定时获取对账单
     * *定时获取各个客户的对账单，下载后，存放在downloadInfo表中，等待定时
     * @throws UnsupportedEncodingException
     */
//    @Scheduled(cron = "0 0 12 * * ?")//每天中午12点
    @RequestMapping(value = "api/getDownLoad.htm")
    public void getDownLoad() throws Exception {
//        String billDate = DateUtil.offsetDay(new DateTime(), -1).toString(DatePattern.PURE_DATE_PATTERN);

        String billDate = "20190108";

        MchConfig mchConfig = new MchConfig();
        mchConfig.setAccntType("0");
        List<MchConfig> mchConfigList = iMchConfigService.listCongi(mchConfig);    //1.查询所有配置商户
        for (MchConfig mchConfig1 : mchConfigList) {
            transactionDetailsService.getDownload(billDate, mchConfig1);
        }
    }


    /**
     * 定时对账
     * *1、核对对账单与上报记账
     * *2、列出差异部分，插入数据库
     * *3、对账单的手续费计入分润账户
     */
    @RequestMapping(value = "api/recondition.htm")
    public void recondition(){
        //按商户查询对账单下载地址
//        String  billDate = DateUtil.offsetDay(new DateTime(), -1).toString(DatePattern.PURE_DATE_PATTERN);

        String billDate = "20190107";

        MchConfig mchConfig = new MchConfig();
        mchConfig.setAccntType("0");
        //1.查询所有配置商户
        List<MchConfig> mchConfigList = iMchConfigService.listCongi(mchConfig);
        for (MchConfig mchConfig1 : mchConfigList) {
            transactionDetailsService.recondition(billDate, mchConfig1);
        }
    }


    @RequestMapping(value="/api/test23.htm")
    public void test() throws Exception {
        String xml = readString4();
        MchConfig mch = new MchConfig();
        Map map = transactionDetailsService.requestXmlToObject(xml,mch);
        List<TransactionDetails> transactionDetailsList = (ArrayList<TransactionDetails>) map.get("transactionDetailList");
        //查询商户的结算通道卡号
        Double amtCount = 0d;
        List<String> attacList = new ArrayList<>();
        for (TransactionDetails transactionDetails : transactionDetailsList) {
            String corrAcctId = transactionDetails.getCorrelateAcctid();//付款卡号
            String attachInfo = transactionDetails.getAttachinfo();//银行唯一交易流水号
            Double trnamt = transactionDetails.getTrnamt();//交易金额
            amtCount += trnamt;
            log.info(trnamt.toString());

        }
        log.info(amtCount.toString());
    }

    private static String readString4()

    {
        int len=0;

        StringBuffer str=new StringBuffer("");

        File file=new File("C:\\Users\\cindy\\Desktop\\Untitled1.txt");

        try {

            FileInputStream is=new FileInputStream(file);

            InputStreamReader isr= new InputStreamReader(is);

            BufferedReader in= new BufferedReader(isr);

            String line=null;

            while( (line=in.readLine())!=null )

            {

                if(len != 0)  // 处理换行符的问题

                {

                    str.append("\r\n"+line);

                }

                else

                {

                    str.append(line);

                }

                len++;

            }

            in.close();

            is.close();

        } catch (IOException e) {

// TODO Auto-generated catch block

            e.printStackTrace();

        }

        return str.toString();

    }

    /**
     **核对余额
     */
    @RequestMapping("/api/reconTest.htm")
    public void reconTest(){
        PassportXyReportDetail passportXyReportDetail = new PassportXyReportDetail();
        passportXyReportDetail.setBeginTime("2018-12-12 00:00:00");
        passportXyReportDetail.setEndTime("2018-12-13 00:00:00");
        List<PassportXyReportDetail> passportXyReportDetailList = passportXyReportDetailMapper.selectDetailByTime(passportXyReportDetail);
        Map<String,String> resultMap;
        for(PassportXyReportDetail passportXyReportDetail1:passportXyReportDetailList){
            //遍历顺网全量数据，调用分账接口
            resultMap = transactionDetailsService.dispatch(passportXyReportDetail1);
            if(ToolUtil.isNotEmpty(resultMap)){
                log.info(resultMap.get("code")+":"+resultMap.get("msg"));
            }
        }
    }

}

